package com.augurit.wf.jbpmex.task.multitask.proxy;

import java.util.List;
import java.util.Set;

import org.hibernate.Session;
import org.jbpm.api.HistoryService;
import org.jbpm.api.JbpmException;
import org.jbpm.api.history.HistoryTask;
import org.jbpm.api.model.Activity;
import org.jbpm.api.model.Transition;
import org.jbpm.api.task.Task;
import org.jbpm.pvm.internal.el.Expression;
import org.jbpm.pvm.internal.env.EnvironmentImpl;
import org.jbpm.pvm.internal.history.model.HistoryTaskImpl;
import org.jbpm.pvm.internal.model.ExecutionImpl;
import org.jbpm.pvm.internal.session.DbSession;
import org.jbpm.pvm.internal.task.TaskDefinitionImpl;
import org.jbpm.pvm.internal.task.TaskImpl;
import org.springside.modules.web.struts2.Struts2Utils;

import com.augurit.common.constant.OrgConstant;
import com.augurit.wf.client.agency.service.IWfAgencyService;
import com.augurit.wf.client.agency.web.form.WfAgencyForm;
import com.augurit.wf.common.constant.WfConstant;
import com.augurit.wf.common.form.WfSendMessageForm;
import com.augurit.wf.common.util.WfUtils;
import com.augurit.wf.jbpmex.assignee.IAssigneeParser;
import com.augurit.wf.jbpmex.task.multitask.MultiTaskDefinition;

/**
 * 以会签计算结果作为跳转transition名称
 */
public abstract class BaseModeProxy implements IModeProxy {


	protected TaskDefinitionImpl taskDefinition;
	protected MultiTaskDefinition multiTaskDefinition;
	protected String[] userKeys;
	protected ExecutionImpl execution;
	protected TaskImpl superTask;
	
	public BaseModeProxy(TaskDefinitionImpl taskDefinition, ExecutionImpl execution){
		
		this.taskDefinition = taskDefinition;
		this.multiTaskDefinition = taskDefinition.getMultiTaskDefinition();
		this.execution = execution;
	}
	public BaseModeProxy(TaskDefinitionImpl taskDefinition, ExecutionImpl execution,TaskImpl superTask){
		
		this.taskDefinition = taskDefinition;
		this.multiTaskDefinition = taskDefinition.getMultiTaskDefinition();
		this.execution = execution;
	}
	public abstract void createSuperTask();

	public abstract void createSubTasks();
	
	public Transition getValidTransition() {
		  Transition transition = null;
		  
			  Activity activity = execution.getActivity();		
				
			  //若开启了自定义流转策略，使用策略获取跳转
			  if(multiTaskDefinition.getTakeTransitionRule() != null){
				  transition = multiTaskDefinition.getTakeTransitionRule().getTransition(execution);
			  }
				
			  //如果无法找到指定跳转并且节点跳转唯一，则直接使用该跳转
			  if(transition == null){
					List<? extends Transition> outgoingTransitions = activity.getOutgoingTransitions();
					if(outgoingTransitions != null && outgoingTransitions.size() >= 1){
						transition = outgoingTransitions.get(0);
					}else
						throw new JbpmException("错误：跳转不唯一！");
			  }else
				  throw new JbpmException("错误：无法找到跳转或不存在跳转！");

		return transition;
	}

	public void createSubTaskInBaseMode(TaskImpl superTask, int index, String assignee, int firstSubTaskIndex){
		DbSession dbSession = this.getBean(DbSession.class);
		IAssigneeParser assigneeParser = this.getBean(IAssigneeParser.class);
		
		TaskImpl subTask = dbSession.createTask();
		subTask.setSuperTask(superTask);
		subTask.setTaskDefinition(taskDefinition);
		subTask.setName(execution.getActivityName() + "_" + assignee);
		subTask.setAssignee(assignee);
		subTask.setSignalling(false);	//false，手工处理execution的跳转
		subTask.setExecution(execution);
		subTask.setProcessInstance(execution.getProcessInstance());
		subTask.setIsMainTask(OrgConstant.ZERO);
		subTask.setTaskType(WfConstant.TASK_TYPE_MULTITASK);
	    subTask.setAssigneeName(assigneeParser.getUserNameByUserKey(assignee));
	    
	    //设置当前节点中文名称
	    subTask.setActivityChineseName(execution.getActivity().getChineseName());
	    
	    //设置代理人信息
	    this.setAgentInfo(subTask);
	    
	    //保存流程提示信息
	    this.setJms(subTask);
	    
	    //如果启用优先顺序
		if(taskDefinition.getMultiTaskDefinition().isUsePriority()){
			
			//设置优先顺序
			subTask.setPriority(index+1);
			
			//打开第一个子任务，其他子任务挂起
			if(index != firstSubTaskIndex)
				subTask.setState(Task.STATE_SUSPENDED);
		}

		//先保存任务再保存汇总信息
		dbSession.save(subTask);

		//创建子任务历史记录
		this.addHistorySubTask(subTask);
	}
	
	/**
	 * 新建与子任务对应的历史子任务
	 * @param subTask
	 */
	public void addHistorySubTask(TaskImpl subTask){
		if(subTask != null && subTask.getSuperTask() != null){
			DbSession dbSession = this.getBean(DbSession.class);
			HistoryTaskImpl superHistoryTask = dbSession.get(HistoryTaskImpl.class, subTask.getSuperTask().getDbid());
			if(superHistoryTask != null){
				HistoryTaskImpl historySubTask = new HistoryTaskImpl(subTask);
				historySubTask.setExecutionId(subTask.getExecution().getId());
				superHistoryTask.addSubTask(historySubTask);
			}
		}
	}
	
	/**
	 * 激活历史任务
	 * @param task
	 */
	public void enableSuspendedHistoryTask(TaskImpl task){
		if(task != null && task.getSuperTask() != null){
			DbSession dbSession = this.getBean(DbSession.class);
			HistoryTaskImpl historyTask = dbSession.get(HistoryTaskImpl.class, task.getDbid());
			if(historyTask != null){
				historyTask.setState(Task.STATE_OPEN);
			}
		}
	}
	
	/**
	 * 获取assignee,如果没有给定expression则从AssigneeRange里获取全部的人
	 * @return
	 */
	public String[] getValidUserKeys(){
		String[] userKeys = null;

		//检查assignee表达式是否为空，如果为空则使用assigneeRange代替
	    WfUtils.replaceRangeForNullAssigneeExp(taskDefinition);
		
		//下一个任务节点assignee表达式
		Expression assigneeExpression = taskDefinition.getAssigneeExpression();
		
		if(assigneeExpression != null) {
			String assignee = (String) assigneeExpression.evaluate(execution);
			IAssigneeParser assigneeParser = EnvironmentImpl.getFromCurrent(IAssigneeParser.class);
			userKeys = assigneeParser.parseToUserKeys(assignee);
		}

		if(userKeys == null || userKeys.length == 0)
			throw new JbpmException("错误：没有指定环节办理人员或者人员范围！");
		  
		return userKeys;
	}
	
	/**
	 * 给定expression获取全部的人
	 * @return
	 */
	public String[] getValidUserKeys(Expression assigneeExpression){
		String[] result = null;
		
		if(assigneeExpression != null) {
			String assignee = (String) assigneeExpression.evaluate(execution);
			IAssigneeParser assigneeParser = EnvironmentImpl.getFromCurrent(IAssigneeParser.class);
			result = assigneeParser.parseToUserKeys(assignee);
		}

		if(result == null || result.length == 0)
			throw new JbpmException("错误：没有指定环节办理人员！");
		  
		return result;
	}
	
	/**
	 * 获取子任务列表
	 * @param superTaskDbId
	 * @return
	 */
	public Set<HistoryTaskImpl> getSubTaskList(Long superTaskDbId){
		if(superTaskDbId != null){
			Session session = this.getBean(Session.class);
			HistoryTaskImpl historySuperTask = (HistoryTaskImpl)session.get(HistoryTaskImpl.class, superTaskDbId);
			if(historySuperTask != null)
				return historySuperTask.getSubTasks();
		}
		return null;
	}
	
	/**
	 * 设置代理人信息
	 * @param task
	 */
	public void setAgentInfo(TaskImpl task){
		IWfAgencyService wfAgencyService = this.getBean(IWfAgencyService.class);
		WfAgencyForm wfAgencyForm = wfAgencyService.getAgentByTask(task);
	    if(wfAgencyForm != null){
	    	task.setAgent(wfAgencyForm.getAgent());
	    	task.setAgentName(wfAgencyForm.getAgentName());
	    	task.setAgentStartDate(wfAgencyForm.getStartDate());
	    	task.setAgentEndDate(wfAgencyForm.getEndDate());
	    }
	}

	public <T> T getBean(Class<T> beanClass){
		return EnvironmentImpl.getFromCurrent(beanClass);
	}
	
	//保存流程提示信息到task
	public void setJms(TaskImpl task){
		String key = WfConstant.VAR_SYS_JMS + execution.getId() + "_" + task.getActivityName();
		WfSendMessageForm form = (WfSendMessageForm)execution.getVariable(key);
		if(form != null)
			task.setJms(Struts2Utils.getJsonString(form));
	}
	
	//去掉表量表的流程提示信息
	public void removeJmsVariable(TaskImpl task){
		String key = WfConstant.VAR_SYS_JMS + execution.getId() + "_" + task.getActivityName();
		execution.removeVariable(key);
	}
	
	/**
	 * 动态新增工作项
	 * @param taskInstDbid
	 * @param assigneeExpression
	 */
	public void createSubTasksInRumtime(TaskImpl superTask, Expression assigneeExpression) {
		if (superTask != null && assigneeExpression != null) {

			String[] assignees = this.getValidUserKeys(assigneeExpression);
			int index = this.getNewSubTaskIndex();
			
			if(assignees != null && assignees.length > 0){
				for(int i=0; i<assignees.length; i++){
					index++;
					this.createSubTaskInBaseMode(superTask, index, assignees[i], 0);
				}
			}
		}
	}

	/**
	 * 获取多工作项个数
	 */
	private int getNewSubTaskIndex(){
		int index = 0;
		HistoryService historyService = this.getBean(HistoryService.class);
		List<HistoryTask> list = historyService.createHistoryTaskQuery().executionId(execution.getId()).list();
		if(list != null && list.size() > 0)
			index = list.size();
		return index;
	}
}
